package com.flashflexpro.tanksinbattle.scene {
import com.flashflexpro.tanksinbattle.scene.dto.DependencyDto;

import com.flashflexpro.tanksinbattle.scene.dto.UrlDependencyDto;

import flash.display.Loader;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.HTTPStatusEvent;
import flash.events.IOErrorEvent;
import flash.events.TimerEvent;
import flash.net.URLRequest;
import flash.system.ApplicationDomain;
import flash.system.LoaderContext;
import flash.utils.Timer;

public class SingleModuleResolver extends EventDispatcher {


    private function onCheckTime(event:TimerEvent):void {
        if( _loader.content != null ){
            onLoaded();
        }
        else{
            trace( _timer.currentCount + " loading " + _loadingArr[ _loadingIndex ] );
        }
    }

    private var _loader:Loader;

    private var _loadingIndex:int = 0;
    private var _loadingArr:Array;

    private var _loadingDependency:DependencyDto;

    public function resolve(sceneDto:DependencyDto, rslEnabled:Boolean ):void {
        _loadingDependency = sceneDto;
        if( rslEnabled && ApplicationDomain.currentDomain.hasDefinition( sceneDto.entryClass ) ){
            onAllDependenciesLoaded();
            return;
        }

        var urld:UrlDependencyDto = sceneDto as UrlDependencyDto;
        if( urld == null ){
            throw new Error( "Unexplected type:" + sceneDto );
        }

        //order matters!
        _loadingArr = [ urld.codeSwfUrl, urld.skinSwfUrl ];
        trace( "resolving code[" + urld.codeSwfUrl + "],[" + urld.skinSwfUrl + "]");
        loadNextDependency();
    }

    private function gc():void {
        if( _timer != null ){
            _timer.stop();
            _timer.removeEventListener( TimerEvent.TIMER, onCheckTime );
        }
        if( _loader != null ){
            _loader.contentLoaderInfo.removeEventListener(Event.COMPLETE, onLoaded);
            _loader.contentLoaderInfo.removeEventListener(IOErrorEvent.IO_ERROR, onIoError);
            _loader.contentLoaderInfo.removeEventListener(HTTPStatusEvent.HTTP_STATUS, onHttpStatus);
        }
    }

    protected function onIoError(event:IOErrorEvent):void {
        dispatchEvent( event );
        gc();
    }


    protected function onHttpStatus(event:HTTPStatusEvent):void {
        if (event.status != 200) {
            trace( "SingleModuleResovle.onHttpStatus[" + event.toString() + "], url:" + _loader.contentLoaderInfo.url );
            dispatchEvent( new IOErrorEvent( IOErrorEvent.IO_ERROR ) );
            gc();
        }
    }

    private function onLoaded(event:Event=null):void {
        gc();
        _loadingIndex ++;
        loadNextDependency();
    }


    private var _timer:Timer = new Timer( 50 );

    private function loadNextDependency():void {
        if (_loadingArr.length > _loadingIndex) {
            _loader = new Loader();
            _loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onLoaded);
            _loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onIoError);
            _loader.contentLoaderInfo.addEventListener(HTTPStatusEvent.HTTP_STATUS, onHttpStatus);

            _timer.addEventListener( TimerEvent.TIMER, onCheckTime );
            _timer.start();

            var currentDependency:String = _loadingArr [ _loadingIndex ] as String;
            if (currentDependency.indexOf("http") != 0) {
                var url:String = _loader.contentLoaderInfo.loaderURL;
                var arr:Array = url.split("/");
                arr.pop();
                currentDependency = arr.join("/") + "/" + currentDependency;
            }
            _loader.load(new URLRequest(currentDependency),new LoaderContext(false, ApplicationDomain.currentDomain));
            trace( "started loading " + currentDependency );
        }
        else {
            onAllDependenciesLoaded();
        }
    }

    protected function onAllDependenciesLoaded():void {
        gc();
        dispatchEvent(new Event(Event.COMPLETE));
    }

}
}